package com.fili.gui.wizards;

import com.fili.gui.WizardFrame;
import com.fili.core.FetchThread;
import com.fili.core.FetchThreadListener;
import com.fili.core.svn.SvnList;
import com.fili.core.svn.SvnEntry;
import com.fili.core.svn.components.SvnTree;
import com.fili.core.svn.components.SvnTreeListener;
import com.fili.core.svn.components.CheckNode;

import org.w3c.dom.*;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.MutableTreeNode;
import java.io.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.Calendar;

/**
 * Created by Claudiu-Florin FILIMON
 * Date: Oct 18, 2006
 * Time: 4:15:22 PM
 * Revision: 0
 */
public class WizardRepo extends WizardPanel implements FetchThreadListener, SvnTreeListener
{
    private SvnTree tree;
    private DefaultMutableTreeNode node;

    public WizardRepo(WizardFrame wizardFrame)
    {
        super(wizardFrame);

        tree = new SvnTree(this);
        tree.setBounds(10, 10, 200, 290);
        add(tree);
    }

    public void fetchThreadFinished(String result, String error, int retVal)
    {
        if (retVal == 0)
        {
            SvnList list = (SvnList) parseXML(result).get(0);


            CheckNode removeMe = (CheckNode) node.getChildAt(0);

            for (int i = 0; i < list.entries.size(); i++)
            {
                SvnEntry e = (SvnEntry) list.entries.get(i);
                System.out.println(e);
                CheckNode n = new CheckNode(e);
                tree.treeModel.insertNodeInto(n, node, 0);
                if (e.kind.equals("dir"))
                    tree.treeModel.insertNodeInto(new CheckNode("PLEASE_WAIT",CheckNode.CHECK_WAIT), n, 0);
            }
//            tree.tree.expandPath(new TreePath(node.getPath()));
            tree.treeModel.removeNodeFromParent(removeMe);
        }
        else
        {
            JOptionPane.showMessageDialog(this, error, "ERROR", JOptionPane.ERROR_MESSAGE);
            getWizardFrame().popWizard();
        }
    }

    public void fetchThreadUpdate(int progress)
    {
    }

    private static String getCharacterDataFromElement(Element e)
    {
        Node child = e.getFirstChild();
        if (child instanceof CharacterData)
        {
            CharacterData cd = (CharacterData) child;
            return cd.getData();
        }
        return "?";
    }

    private SvnEntry getEntry(Element e, String path)
    {
        SvnEntry entry = new SvnEntry();
        entry.kind = e.getAttribute("kind");
        entry.fullPath = path;            

        NodeList nodes = e.getElementsByTagName("name");
        if (nodes.getLength() > 0)
        {
            entry.name = getCharacterDataFromElement((Element) nodes.item(0));
        }
        nodes = e.getElementsByTagName("commit");
        if (nodes.getLength() > 0)
        {
            e = (Element) nodes.item(0);
            entry.commitRevision = Integer.parseInt(e.getAttribute("revision"));
            nodes = e.getElementsByTagName("author");
            if (nodes.getLength() > 0)
                entry.commitAuthor = getCharacterDataFromElement((Element) nodes.item(0));
            nodes = e.getElementsByTagName("date");
            if (nodes.getLength() > 0)
            {
                String s = getCharacterDataFromElement((Element) nodes.item(0));
                Calendar calendar = Calendar.getInstance();
                int dYear, dMonth, dDay;
                int dHour, dMin, dSec;

                dYear = Integer.parseInt(s.substring(0, 4));
                dMonth = Integer.parseInt(s.substring(5, 7)) - 1;
                dDay = Integer.parseInt(s.substring(8, 10));
                dHour = Integer.parseInt(s.substring(11, 13));
                dMin = Integer.parseInt(s.substring(14, 16));
                dSec = Integer.parseInt(s.substring(17, 19));
                calendar.set(dYear, dMonth, dDay, dHour, dMin, dSec);

                entry.commitDate = calendar.getTime();
            }
        }

        return entry;
    }

    private SvnList getList(Element e)
    {
        SvnList list = new SvnList();
        NodeList nodes = e.getElementsByTagName("entry");
        for (int i = 0; i < nodes.getLength(); i++)
            list.entries.add(getEntry((Element) nodes.item(i), e.getAttribute("path")));
        return list;
    }

    public ArrayList parseXML(String xml)
    {
        try
        {
            DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
            Document doc = builder.parse(new ByteArrayInputStream(xml.getBytes()));

            ArrayList lists = new ArrayList();
            NodeList nodes = doc.getElementsByTagName("lists");
            for (int i = 0; i < nodes.getLength(); i++)
            {
                NodeList nd = ((Element) nodes.item(i)).getElementsByTagName("list");
                for (int j = 0; j < nd.getLength(); j++)
                    lists.add(getList((Element) nd.item(j)));
            }
            return lists;
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }

        return null;
    }

    public void populateNode(CheckNode node)
    {
        this.node = node;
        String path = getWizSettings().svnRepo;
        if (node != null)
        {
            if (node.getUserObject() instanceof SvnEntry)
            {
                SvnEntry entry = (SvnEntry) node.getUserObject();
                path = entry.fullPath+"/"+entry.name;
            }
        }
        new FetchThread("svn list " + path + " --xml", this);
    }
}
